import os
import platform
import time
import logging
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler


class CrossPlatformFolderHandler(FileSystemEventHandler):
    def __init__(self):
        super().__init__()
        self.system = platform.system()
        self.last_renamed = None
        self.last_time = 0
        self.max_retries = 3  # 最大重试次数
        self.retry_delay = 0.5  # 重试延迟(秒)
        self.fs_ready_timeout = 2.0  # 文件系统就绪等待超时(秒)

        # 配置日志
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s - %(levelname)s - %(message)s',
            handlers=[
                logging.FileHandler(os.path.expanduser('~/folder_sync.log')),
                logging.StreamHandler()
            ]
        )

        # 平台特定配置
        if self.system == 'Darwin':
            self.exclude_files = {'.DS_Store'}
            self.exclude_dirs = {'.Trash', '.fseventsd'}
        elif self.system == 'Windows':
            self.exclude_files = {'Thumbs.db', 'desktop.ini'}
            self.exclude_dirs = {'$RECYCLE.BIN', 'System Volume Information'}
        else:
            self.exclude_files = set()
            self.exclude_dirs = set()

    def wait_for_filesystem(self, path):
        """等待文件系统就绪"""
        start_time = time.time()
        while time.time() - start_time < self.fs_ready_timeout:
            if os.path.exists(path):
                return True
            time.sleep(0.1)
        return False

    def safe_rename(self, old_path, new_path, filename):
        """安全重命名函数，包含重试机制"""
        old_path = os.path.normpath(old_path.strip())
        new_path = os.path.normpath(new_path.strip())
        
        for attempt in range(self.max_retries):
            try:
                # 等待文件系统就绪
                if not self.wait_for_filesystem(old_path):
                    raise OSError(f"文件系统未就绪: {old_path}")
                
                # 执行重命名
                os.rename(old_path, new_path)
                
                # 验证重命名结果
                if os.path.exists(new_path):
                    logging.info(f"重命名成功: {filename}")
                    return True
                else:
                    raise RuntimeError("重命名后文件未出现")
                    
            except Exception as e:
                if attempt < self.max_retries - 1:
                    logging.warning(f"重命名失败(尝试 {attempt + 1}/{self.max_retries}): {filename} - {str(e)}")
                    time.sleep(self.retry_delay * (attempt + 1))
                else:
                    logging.error(f"重命名最终失败: {filename} - {str(e)}")
        return False

    def on_moved(self, event):
        """处理文件夹重命名事件"""
        if not event.is_directory:
            return

        current_time = time.time()
        if event.dest_path != self.last_renamed or current_time - self.last_time > 1:
            self.last_renamed = event.dest_path
            self.last_time = current_time

            old_name = os.path.basename(event.src_path)
            new_name = os.path.basename(event.dest_path)

            logging.info(f"检测到文件夹重命名: {old_name} → {new_name}")
            # 添加延迟确保文件系统更新
            time.sleep(0.5)
            self.sync_filenames(event.dest_path, old_name, new_name)

    def sync_filenames(self, folder_path, old_text, new_text):
        """同步更新文件夹内文件名"""
        for root, dirs, files in os.walk(folder_path, topdown=True):
            # 排除特定目录
            dirs[:] = [d for d in dirs if d not in self.exclude_dirs]

            for file in files:
                if file in self.exclude_files:
                    continue

                if old_text in file:
                    old_path = os.path.join(root, file)
                    new_file = file.replace(old_text, new_text)
                    new_path = os.path.join(root, new_file)
                    
                    self.safe_rename(old_path, new_path, file)


def get_default_watch_path():
    """获取平台默认监控路径"""
    system = platform.system()
    if system == 'Darwin':
        return os.path.expanduser('~/Documents')
    elif system == 'Windows':
        return os.path.join(os.environ['USERPROFILE'], 'Documents')
    else:
        return os.path.expanduser('~')


def start_monitoring(path=None):
    """启动文件监控"""
    if path is None:
        path = get_default_watch_path()

    if not os.path.exists(path):
        logging.error(f"监控路径不存在: {path}")
        return

    event_handler = CrossPlatformFolderHandler()
    observer = Observer()

    try:
        observer.schedule(event_handler, path, recursive=True)
        observer.start()
        logging.info(f"开始监控: {path} (按Ctrl+C停止)")

        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    finally:
        observer.join()


if __name__ == "__main__":
    # 可以在这里指定自定义路径，或使用默认路径
    custom_path = "D:\\"
    # start_monitoring()  # 使用默认路径
    start_monitoring(custom_path)  # 使用自定义路径